from rest_framework.decorators import action
from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response
from django.conf import settings
from datetime import datetime
from time import sleep

from apps.new_gateway.tasks import *
from .serializer import GatewayIdSerializer
from util.exception import ValidationError
from apps.missions.models import *
from apps import redis_client


class NewGatewayViewset(GenericViewSet):
    @action(detail=False, methods=["GET", ], url_path="awake")
    def dir_path(self, requests, *args, **kwargs):
        try:
            data = {}
            data["gateway_id"] = requests.GET.get("gateway_id")
            check_seriailizer = GatewayIdSerializer(data=data)
            missions = []
            exists_mission_number = []
            if check_seriailizer.is_valid():
                gateway_id = check_seriailizer.validated_data.get("gateway_id")
                gateway = Gateway.objects.filter(gateway_id=gateway_id).first()
                if gateway:
                    is_running = int(gateway.is_running)
                    if not is_running:
                        agreement_mission = Mission.objects.filter(gateway_id=gateway_id, is_again=False, state=0,
                                                                   mission_number=settings.AGREEMENT_GATEWAY).order_by(
                            "-create_date").first()
                        main_mission = Mission.objects.filter(gateway_id=gateway_id, is_again=False, state=0,
                                                              mission_number=settings.MAIN_GATEWAY).order_by(
                            "-create_date").first()
                        read_mission = Mission.objects.filter(gateway_id=gateway_id, is_again=False, state=0,
                                                              mission_number=settings.READ_GATEWAY).order_by(
                            "-create_date").first()
                        config_mission = Mission.objects.filter(gateway_id=gateway_id, is_again=False, state=0,
                                                                mission_number=settings.CONFIG_GATEWAY).order_by(
                            "-create_date").first()
                        reboot_mission = Mission.objects.filter(gateway_id=gateway_id, is_again=False, state=0,
                                                                mission_number=settings.REBOOT_GATEWAY).order_by(
                            "-create_date").first()
                        if agreement_mission:
                            missions.append(agreement_mission)
                            Mission.objects.filter(gateway_id=gateway_id, is_again=False, state=0,
                                                   mission_number=settings.AGREEMENT_GATEWAY).exclude(
                                id=agreement_mission.id).update(state=-1)
                        if main_mission:
                            missions.append(main_mission)
                            Mission.objects.filter(gateway_id=gateway_id, is_again=False, state=0,
                                                   mission_number=settings.MAIN_GATEWAY).exclude(
                                id=main_mission.id).update(state=-1)
                        if read_mission:
                            missions.append(read_mission)
                            Mission.objects.filter(gateway_id=gateway_id, is_again=False, state=0,
                                                   mission_number=settings.READ_GATEWAY).exclude(
                                id=read_mission.id).update(state=-1)
                        if config_mission:
                            missions.append(config_mission)
                            Mission.objects.filter(gateway_id=gateway_id, is_again=False, state=0,
                                                   mission_number=settings.CONFIG_GATEWAY).exclude(
                                id=config_mission.id).update(state=-1)
                        if reboot_mission:
                            missions.append(reboot_mission)
                            Mission.objects.filter(gateway_id=gateway_id, is_again=False, state=0,
                                                   mission_number=settings.REBOOT_GATEWAY).exclude(
                                id=reboot_mission.id).update(state=-1)
                    if missions:
                        self.__start_loop(gateway_id)
                        now_tid = self.__set_now_task_id(gateway_id)
                        for mission in missions:
                            mission_number = mission.mission_number
                            if mission_number not in exists_mission_number:
                                exists_mission_number.append(mission_number)
                                file_path = mission.file_path
                                if file_path:
                                    mission_parameter = file_path
                                else:
                                    mission_parameter = ""
                                mission_id = mission.id
                                mission.state = 0
                                mission.save()
                                sleep(0.8)
                                self.pub_mission(mission_number, mission_parameter, mission_id, now_tid)
                                self.__delay_mission(mission_number, mission_parameter, mission_id, now_tid)
                    return Response({
                        "code": 200,
                        "count": len(missions)
                    })
                else:
                    raise ValidationError(30002)
            else:
                raise ValidationError(20001)
        except Exception as e:
            print(e)
            return Response({
                "code": 200,
                "count": str(e)
            })

    def __start_loop(self, gateway_id):
        string = "".join([str(gateway_id), "start_loop"])
        redis_client.set(string, 0)

    def __set_now_task_id(self, gateway_id):
        string = "{}{}".format(gateway_id, "now_tid")
        now_tid = redis_client.incr(string)
        return now_tid

    def __delay_mission(self, mission_number, mission_parameter, mission_id, now_tid):
        if mission_number == settings.REBOOT_GATEWAY:
            reboot_gateway_task.delay({"mission_id": mission_id, "now_tid": now_tid})
        elif mission_number == settings.READ_GATEWAY:
            read_gateway_task.delay({"mission_id": mission_id, "now_tid": now_tid})
        elif mission_number == settings.AGREEMENT_GATEWAY:
            agreement_task.delay({"mission_id": mission_id, "file_name": mission_parameter, "now_tid": now_tid})
        elif mission_number == settings.MAIN_GATEWAY:
            main_task.delay({"mission_id": mission_id, "file_name": mission_parameter, "now_tid": now_tid})
        elif mission_number == settings.CONFIG_GATEWAY:
            config_task.delay({"mission_id": mission_id, "file_name": mission_parameter, "now_tid": now_tid})
        elif mission_number == settings.POWEROFF:
            poweroff_gateway_task.delay({"mission_id": mission_id})

    def pub_mission(self, mission_number, mission_parameter, mission_id, now_tid):
        if mission_number == settings.REBOOT_GATEWAY:
            reboot_gateway_task({"mission_id": mission_id, "now_tid": now_tid, "is_pub": True})
        elif mission_number == settings.READ_GATEWAY:
            read_gateway_task({"mission_id": mission_id, "now_tid": now_tid, "is_pub": True})
        elif mission_number == settings.AGREEMENT_GATEWAY:
            agreement_task(
                {"mission_id": mission_id, "file_name": mission_parameter, "now_tid": now_tid, "is_pub": True})
        elif mission_number == settings.MAIN_GATEWAY:
            main_task({"mission_id": mission_id, "file_name": mission_parameter, "now_tid": now_tid, "is_pub": True})
        elif mission_number == settings.CONFIG_GATEWAY:
            config_task({"mission_id": mission_id, "file_name": mission_parameter, "now_tid": now_tid, "is_pub": True})
        elif mission_number == settings.POWEROFF:
            poweroff_gateway_task({"mission_id": mission_id})

